package timing.ukulele.flow.provider;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import timing.ukulele.cache.Cache;
import timing.ukulele.flow.request.SetTaskAssigneeReq;
import timing.ukulele.flow.service.OperateTaskService;
import timing.ukulele.flow.util.JumpAnyWhereCmd;
import timing.ukulele.flow.util.ProcessImageManager;
import timing.ukulele.flow.vo.ExecuteVO;
import timing.ukulele.flow.vo.ProcessInstanceVO;
import timing.ukulele.flow.vo.TaskVO;
import timing.ukulele.flow.vo.UserVO;
import timing.ukulele.common.ResponseResult;
import timing.ukulele.flow.exception.NoUserException;
import timing.ukulele.flow.extention.UserTaskExtensionElementProperty;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.db.DbSqlSessionFactory;
import org.activiti.engine.impl.db.ListQueryParameterObject;
import org.activiti.engine.impl.persistence.entity.*;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.ExceptionTranslationStrategy;
import org.springframework.data.redis.FallbackExceptionTranslationStrategy;
import org.springframework.data.redis.connection.jedis.JedisConverters;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 提供给业务方调用的接口
 */
@RestController
@RequestMapping("/provider")
@Api(tags = "流程相关操作接口")
@Slf4j
public class FlowProvider implements UserTaskExtensionElementProperty {

    @Autowired
    Cache cache;

    @Autowired
    private OperateTaskService operateTaskService;

    public static final int I_NO_OPERATION = 0;

    public static final int I_DONE = 1;

    public static final int I_TASK_NOT_FOUND = 2;

    public static final int I_ROLLBACK = 3;

    private final ProcessImageManager processImageManager;
    private final RuntimeService runtimeService;
    private final ProcessEngine processEngine;
    private final TaskService taskService;
    private final HistoryService historyService;
    private final RepositoryService repositoryService;


    private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION =
            new FallbackExceptionTranslationStrategy(JedisConverters.exceptionConverter());


    public FlowProvider(ProcessImageManager processImageManager, RuntimeService runtimeService,
                        ProcessEngine processEngine, TaskService taskService, HistoryService historyService,
                        RepositoryService repositoryService) {
        this.processImageManager = processImageManager;
        this.runtimeService = runtimeService;
        this.processEngine = processEngine;
        this.taskService = taskService;
        this.historyService = historyService;
        this.repositoryService = repositoryService;
    }

    @GetMapping("/test/getUser")
    public ResponseResult<List<UserVO>> testGetUser(
            @RequestParam(value = "userpara", required = false) String userpara,
            @RequestParam(value = "uuid", required = false) String uuid,
            @RequestParam(value = "depcode", required = false) String depcode,
            @RequestParam(value = "areacode", required = false) String areacode,
            @RequestParam(value = "roles", required = false) String roles,
            @RequestParam(value = "isand", required = false) String isand,
            @RequestParam(value = "usertype", required = false) String usertype,
            @RequestParam(value = "startuser", required = false) String startuser,
            @RequestParam(value = "flowuser", required = false) String flowuser,
            @RequestParam(value = "rulecode", required = false) String rulecode
    ) {
        List<UserVO> userVOS = operateTaskService.testGetUser(userpara, uuid, depcode, areacode, roles, isand, usertype, startuser, flowuser, rulecode);
        return ResponseResult.success(userVOS);
    }

    @PostMapping(path = "/start")
    @ApiOperation(value = "开始任务",
            notes = "开始任务，任务进入下一个节点。参数必传processKey(流程定义的key)，startUser(启动用户)和(nextAssignee(下步执行人)"
                    + "或uuid或departs或areacode或roles或isand或usertype或rulecode或userpara)和tenantId(租户id即系统id)，其他参数根据所配置的流程节点传。")
    public ResponseResult<Map<String, Object>> start(@RequestBody ExecuteVO executeVO) {
        if (executeVO == null) {
            return ResponseResult.error("参数不能为空");
        }
        if (StringUtils.isEmpty(executeVO.getProcessKey()) || StringUtils.isEmpty(executeVO.getStartUser())
                || StringUtils.isEmpty(executeVO.getTenantId())) {
            return ResponseResult.error("参数中必须包含processKey和startUser和tenantId");
        }
        try {
            return ResponseResult.success(operateTaskService.start(executeVO));
        } catch (Exception e) {
            if (e instanceof NoUserException) {
                return ResponseResult.error("启动失败:" + e.getMessage());
            }
            log.error(e.getMessage());
            return ResponseResult.error("启动失败:" + e.getMessage());
        }
    }

    @PostMapping(path = "/noPreCompleteTask")
    @ApiOperation(value = "无锁执行任务",
            notes = "无锁完成任务，任务进入下一个节点。参数必传processInstanceId(流程实例id)，assignee(当前执行人)和(nextAssignee(下步执行人)"
                    + "或uuid或departs或areacode或roles或island或usertype或rulecode或userpara)和taskId(任务id)，其他参数根据所配置的流程节点传。")
    public ResponseResult<List<TaskVO>> noPreCompleteTask(@RequestBody ExecuteVO executeVO) {
        List<TaskVO> taskVOS;
        double start = System.currentTimeMillis();
        log.info("无锁任务接口开始时间:" + start);
        if (executeVO == null) {
            return ResponseResult.error("参数不能为空");
        }
        if (StringUtils.isEmpty(executeVO.getProcessInstanceId()) || StringUtils.isEmpty(executeVO.getAssignee())
                || StringUtils.isEmpty(executeVO.getTaskId())) {
            return ResponseResult.error("参数中必须包含processInstanceId,assignee,taskId");
        }
        try {
            taskVOS = operateTaskService.completeTask(executeVO);
        } catch (Exception e) {
            if (e instanceof NoUserException) {
                return ResponseResult.error("启动失败:" + e.getMessage());
            }
            log.error(e.getMessage());
            return ResponseResult.error("执行失败:" + e.getMessage());
        }
        double end = System.currentTimeMillis();
        log.info("无锁任务接口结束时间:" + end);
        log.info("无锁任务接口用时：" + (end - start) / 1000 + "秒");
        return ResponseResult.success(taskVOS);
    }

    @PostMapping(path = "/completeTask")
    @ApiOperation(value = "执行任务",
            notes = "完成任务，任务进入下一个节点。参数必传processInstanceId(流程实例id)，assignee(当前执行人)和(nextAssignee(下步执行人)"
                    + "或uuid或departs或areacode或roles或island或usertype或rulecode或userpara)和taskId(任务id)，其他参数根据所配置的流程节点传。")
    public ResponseResult<List<TaskVO>> completeTask(@RequestBody ExecuteVO executeVO) {
        if (executeVO == null) {
            return ResponseResult.error("参数不能为空");
        }
        if (StringUtils.isEmpty(executeVO.getProcessInstanceId()) || StringUtils.isEmpty(executeVO.getAssignee())
                || StringUtils.isEmpty(executeVO.getTaskId()) || StringUtils.isEmpty(executeVO.getTransactionId())) {
            return ResponseResult.error("参数中必须包含processInstanceId,assignee,taskId,transactionId");
        }
        String taskId = executeVO.getTaskId();
        String transactionId = executeVO.getTransactionId();
        try {
            //先校验该任务是否为预处理的任务
            Object cacheObject = cache.get("timing_flow_task_lock_" + taskId);
            String value = null;
            if (cacheObject != null)
                value = (String) cacheObject;
            if (StringUtils.isEmpty(value)) {
                return ResponseResult.error("该任务没有预处理过,不能执行完成该任务!");
            } else {
                if (value.equals(transactionId)) {
                    //已预处理，可以执行完成任务
                    List<TaskVO> taskVOS = operateTaskService.completeTask(executeVO);
                    cache.remove("timing_flow_task_lock_" + taskId);
                    return ResponseResult.success(taskVOS);
                } else {
                    return ResponseResult.error("该任务没有预处理过,不能执行完成该任务!");
                }
            }
        } catch (Exception e) {
            if (e instanceof NoUserException) {
                return ResponseResult.error("启动失败:" + e.getMessage());
            }
            log.error(e.getMessage());
            return ResponseResult.error("执行失败:" + e.getMessage());
        }
    }

    @PostMapping(path = "/preCompleteTask")
    @ApiOperation(value = "预处理执行任务", notes = "预处理执行任务。参数必传taskId(任务id)，transactionId(锁密id，特点:唯一,随机)")
    public ResponseResult preCompleteTask(
            @ApiParam(value = "任务id", required = true) @RequestParam("taskId") String taskId,
            @ApiParam(value = "锁密id", required = true) @RequestParam("transactionId") String transactionId) {
        if (StringUtils.isEmpty(taskId) || StringUtils.isEmpty(transactionId)) {
            return ResponseResult.error("参数taskId和transactionId都为必传参数!");
        }
        try {
            //先从redis里取以task_lock_taskId为key的value,如果没有则创建，如果有则校验transactionId值
            Object cacheObject = cache.get("timing_flow_task_lock_" + taskId);
            String value = null;
            if (cacheObject != null)
                value = (String) cacheObject;
            if (StringUtils.isEmpty(value)) {
                //加锁
                cache.put("timing_flow_task_lock_" + taskId, transactionId);
            } else {
                if (!value.equals(transactionId)) {
                    return ResponseResult.error("该任务已预处理,请先释放!");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("预处理执行任务失败:" + e.getMessage());
        }
        return ResponseResult.success("预处理执行任务成功:");
    }

    @PostMapping(path = "/rollBackCompleteTask")
    @ApiOperation(value = "释放预处理执行任务", notes = "释放预处理执行任务。参数必传taskId(任务id)，transactionId(锁密id，特点:唯一,随机)")
    public ResponseResult rollBackCompleteTask(
            @ApiParam(value = "任务id", required = true) @RequestParam("taskId") String taskId,
            @ApiParam(value = "锁密id", required = true) @RequestParam("transactionId") String transactionId) {
        if (StringUtils.isEmpty(taskId) || StringUtils.isEmpty(transactionId)) {
            return ResponseResult.error("参数taskId和transactionId都为必传参数!");
        }
        try {
            //先从redis里取以task_lock_taskId为key的value,校验是否为真实主人
            Object cacheObject = cache.get("timing_flow_task_lock_" + taskId);
            String value = null;
            if (cacheObject != null)
                value = (String) cacheObject;
            if (StringUtils.isEmpty(value)) {
                //校验失败
                return ResponseResult.error("该任务没有被预先处理,请先预处理!");
            } else {
                if (value.equals(transactionId)) {
                    //校验成功
                    cache.remove("timing_flow_task_lock_" + taskId);
                    return ResponseResult.success("释放预处理执行任务成功!");
                } else {
                    return ResponseResult.error("该任务没有被预先处理,请先预处理!");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("释放预处理执行任务失败:" + e.getMessage());
        }
    }

    @PostMapping(path = "/setTaskAssignee")
    @ApiOperation(value = "流程执行过程中给task赋执行人", notes = "流程执行过程中给task赋执行人")
    public ResponseResult<String> setTaskAssignee(@RequestBody List<SetTaskAssigneeReq> setTaskAssigneeReqs) {
        try {
            if (CollectionUtils.isEmpty(setTaskAssigneeReqs)) {
                return ResponseResult.error("setTaskAssigneeReqs集合为空!");
            }
            for (SetTaskAssigneeReq setTaskAssigneeReq : setTaskAssigneeReqs) {
                String taskId = setTaskAssigneeReq.getTaskId();
                String users = setTaskAssigneeReq.getUsers();
                String departs = setTaskAssigneeReq.getDeparts();
                String roles = setTaskAssigneeReq.getRoles();
                String currentUser = setTaskAssigneeReq.getCurrentUser();
                if (StringUtils.isEmpty(taskId)) {
                    return ResponseResult.error("存在task必传参数taskId没有传值!");
                }
                if (StringUtils.isEmpty(currentUser)) {
                    return ResponseResult.error("存在task必传参数currentUser没有传值!");
                }
                if (StringUtils.isEmpty(users) && StringUtils.isEmpty(departs) && StringUtils.isEmpty(roles)) {
                    return ResponseResult.error("存在task查找执行人相关参数没有传值!");
                }
            }
            operateTaskService.setTaskAssignee(setTaskAssigneeReqs);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("给任务指定执行人失败!" + e.getMessage());
        }
        return ResponseResult.success("给任务指定执行人执行成功！");
    }

    @PostMapping(path = "/claimTask")
    @ApiOperation(value = "根据taskId拾取任务", notes = "根据taskId拾取任务，对于组任务让指定候选人拾取该任务，参数必传taskId(任务id)，candidateUser(拾取者)")
    public ResponseResult claimTask(@ApiParam(value = "任务id", required = true) @RequestParam("taskId") String taskId,
                                    @ApiParam(value = "拾取任务的候选人", required = true) @RequestParam("candidateUser") String candidateUser) {
        try {
            if (StringUtils.isEmpty(taskId) || StringUtils.isEmpty(candidateUser)) {
                return ResponseResult.error("参数taskId和candidateUser都必须传值!");
            }
            taskService.claim(taskId, candidateUser);
            return ResponseResult.success("拾取任务成功");
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("拾取任务失败:" + e.getMessage());
        }
    }

    @PostMapping(path = "/returnOrTransferTask")
    @ApiOperation(value = "根据taskId归还或者任务转接", notes = "根据taskId归还或者任务转接，参数必传taskId(任务id)，assignee(任务接收者)。")
    public ResponseResult returnOrTransferTask(
            @ApiParam(value = "任务id", required = true) @RequestParam("taskId") String taskId,
            @ApiParam(value = "任务接收者") @RequestParam("assignee") String assignee) {
        try {
            if (StringUtils.isEmpty(taskId)) {
                return ResponseResult.error("参数taskId必须传值!");
            }
            //当assignee为null时，task归还给任务组，不为null时为任务转接
            taskService.setAssignee(taskId, assignee);
            return ResponseResult.success("任务归还或者转接成功");
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("任务归还或者转接失败:" + e.getMessage());
        }
    }

    @PostMapping(path = "/findUndoTaskByAssignee")
    @ApiOperation(value = "根据流程assignee查询当前人的待办任务",
            notes = "根据流程assignee查询当前人的待办任务。返回值为包含taskID(任务ID),taskName(任务名称),taskCreateTime(任务的创建时间),taskAssignee(任务的办理人),processInstanceId(流程实例ID),executionId(执行对象ID),processDefinitionId(流程定义ID)字段的列表")
    public ResponseResult<Page<TaskVO>> findUnDoTaskByAssignee(
            @ApiParam("代理人（用户）") @RequestParam(value = "assignee", required = false) String assignee,
            @ApiParam("租户id") @RequestParam("tenantId") String tenantId,
            @ApiParam(value = "变量名") @RequestParam(value = "variableName", required = false) String variableName,
            @ApiParam(value = "变量值") @RequestParam(value = "variableValue", required = false) String variableValue,
            @ApiParam(value = "变量名Like") @RequestParam(value = "variableNameLike", required = false) String variableNameLike,
            @ApiParam(value = "变量值Like") @RequestParam(value = "variableValueLike", required = false) String variableValueLike,
            @ApiParam(value = "流程定义Key,多个用英文','隔开") @RequestParam(value = "processDefinedKey", required = false) String processDefinitionKey,
            @ApiParam(value = "流程实例id") @RequestParam(value = "processInstanceId", required = false) String processInstanceId,
            @ApiParam(value = "流程节点Key") @RequestParam(value = "taskKey", required = false) String taskKey,
            @ApiParam(value = "创建时间排序方向:1代表时间升序、-1代表时间降序") @RequestParam("sort") Integer sort,
            @ApiParam(value = "当前页码", example = "1") @RequestParam("current") Integer current,
            @ApiParam(value = "每页大小", example = "10") @RequestParam("pageSize") Integer pageSize) {
        //创建任务查询对象
        List<Task> taskList;
        TaskQuery taskQuery;
        if (sort == 1) {
            taskQuery = taskService.createTaskQuery().taskTenantId(tenantId).orderByTaskCreateTime().asc();
        } else if (sort == -1) {
            taskQuery = taskService.createTaskQuery().taskTenantId(tenantId).orderByTaskCreateTime().desc();
        } else {
            //默认按升序
            taskQuery = taskService.createTaskQuery().taskTenantId(tenantId);
        }

        try {
            if (StringUtils.hasLength(assignee)) {
                taskQuery.taskCandidateOrAssigned(assignee);
            }
            if (StringUtils.hasLength(variableName) && StringUtils.hasLength(variableValue)) {
                taskQuery.taskVariableValueEquals(variableName, variableValue);
            }
            if (StringUtils.hasLength(processDefinitionKey)) {
                String[] split = processDefinitionKey.split(",");
                if (split.length > 1) {
                    List<String> stringList = Arrays.asList(split);
                    taskQuery.processDefinitionKeyIn(stringList);
                } else {
                    taskQuery.processDefinitionKey(processDefinitionKey);
                }
            }
            if (StringUtils.hasLength(processInstanceId)) {
                taskQuery.processInstanceId(processInstanceId);
            }
            if (StringUtils.hasLength(taskKey)) {
                taskQuery.taskDefinitionKey(taskKey);
            }
            if (StringUtils.hasLength(variableNameLike) && StringUtils.hasLength(variableValueLike)) {
                taskQuery.taskVariableValueLike(variableNameLike, variableValueLike);
            }
            taskList = taskQuery.listPage((current - 1) * pageSize, pageSize);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("查询失败：" + e.getMessage());
        }
        if (!CollectionUtils.isEmpty(taskList)) {
            List<TaskVO> resultList = new ArrayList<>();
            for (Task task : taskList) {
                TaskVO vo = new TaskVO();
                if (StringUtils.isEmpty(task.getAssignee())) {
                    List<IdentityLink> identityLinksForTask =
                            taskService.getIdentityLinksForTask(task.getId());
                    if (!CollectionUtils.isEmpty(identityLinksForTask)) {
                        StringBuffer stringBuffer = new StringBuffer();
                        for (int i = 0; i < identityLinksForTask.size(); i++) {
                            if (!StringUtils.isEmpty(identityLinksForTask.get(i).getUserId())) {
                                if (i == identityLinksForTask.size() - 1) {
                                    stringBuffer.append(identityLinksForTask.get(i).getUserId());
                                } else {
                                    stringBuffer.append(identityLinksForTask.get(i).getUserId() + ",");
                                }
                                vo.setCandidate(stringBuffer.toString());
                            }
                        }
                    }
                }
                BeanUtils.copyProperties(task, vo);
                vo.setProperties(operateTaskService.findRunningTaskParams(task));
                Map<String, VariableInstance> variableInstances = taskService.getVariableInstances(task.getId());
                if (!CollectionUtils.isEmpty(variableInstances)) {
                    if (vo.getRunningVariables() == null) {
                        vo.setRunningVariables(new ArrayList<>(variableInstances.size()));
                    }
                    variableInstances.forEach((key, value) ->
                    {
                        vo.getRunningVariables().add((VariableInstanceEntityImpl) value);
                    });
                }
                vo.setTaskType(0);
                //任务锁状态
                vo.setLocked(checkTaskLock(task.getId()));
                resultList.add(vo);
            }
            Page<TaskVO> page = new Page<>(current, pageSize);
            page.setRecords(resultList);
            page.setTotal(taskQuery.count());
            return ResponseResult.success(page);
        } else {
            return ResponseResult.success(null);
        }
    }

    @PostMapping(path = "/findNoUserTask")
    @ApiOperation(value = "查询无人异常任务",
            notes = "根据系统id查询无人异常任务。返回值为包含taskID(任务ID),taskName(任务名称),taskCreateTime(任务的创建时间),taskAssignee(任务的办理人),processInstanceId(流程实例ID),executionId(执行对象ID),processDefinitionId(流程定义ID)字段的列表")
    public ResponseResult findNoUserTask(@ApiParam("租户id") @RequestParam("tenantId") String tenantId,
                                         @ApiParam(value = "变量名") @RequestParam(value = "variableName", required = false) String variableName,
                                         @ApiParam(value = "变量值") @RequestParam(value = "variableValue", required = false) String variableValue,
                                         @ApiParam(value = "当前页码", example = "1") @RequestParam("current") Integer current,
                                         @ApiParam(value = "每页大小", example = "10") @RequestParam("pageSize") Integer pageSize) {
        //创建任务查询对象
        List<Task> taskList;
        try {
            TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(null).taskTenantId(tenantId);
            if (StringUtils.hasLength(variableName) && StringUtils.hasLength(variableValue)) {
                taskQuery.taskVariableValueEquals(variableName, variableValue);
            }
            taskList = taskQuery.listPage((current - 1) * pageSize, pageSize);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("查询失败：" + e.getMessage());
        }
        if (!CollectionUtils.isEmpty(taskList)) {
            List<TaskVO> resultList = new ArrayList<>();
            for (Task task : taskList) {
                TaskVO vo = new TaskVO();
                BeanUtils.copyProperties(task, vo);
                vo.setProperties(operateTaskService.findRunningTaskParams(task));
                Map<String, VariableInstance> variableInstances = taskService.getVariableInstances(task.getId());
                if (!CollectionUtils.isEmpty(variableInstances)) {
                    if (vo.getRunningVariables() == null) {
                        vo.setRunningVariables(new ArrayList<>(variableInstances.size()));
                    }
                    variableInstances.forEach((key, value) ->
                    {
                        vo.getRunningVariables().add((VariableInstanceEntityImpl) value);
                    });
                }
                vo.setTaskType(0);
                //任务锁状态
                vo.setLocked(checkTaskLock(task.getId()));
                resultList.add(vo);
            }
            Page<TaskVO> page = new Page<>(current, pageSize);
            page.setRecords(resultList);
            page.setTotal(taskService.createTaskQuery().taskCandidateOrAssigned(null).taskTenantId(tenantId).count());
            return ResponseResult.success(page);
        } else {
            return ResponseResult.success(null);
        }
    }

    @PostMapping(path = "/findOverDueTask")
    @ApiOperation(value = "查询过期异常任务",
            notes = "根据系统id查询过期异常任务。返回值为包含taskID(任务ID),taskName(任务名称),taskCreateTime(任务的创建时间),taskAssignee(任务的办理人),processInstanceId(流程实例ID),executionId(执行对象ID),processDefinitionId(流程定义ID)字段的列表")
    public ResponseResult findOverDueTask(@ApiParam("租户id") @RequestParam("tenantId") String tenantId,
                                          @ApiParam(value = "变量名") @RequestParam(value = "variableName", required = false) String variableName,
                                          @ApiParam(value = "变量值") @RequestParam(value = "variableValue", required = false) String variableValue,
                                          @ApiParam(value = "当前页码", example = "1") @RequestParam("current") Integer current,
                                          @ApiParam(value = "每页大小", example = "10") @RequestParam("pageSize") Integer pageSize) {
        //创建任务查询对象
        List<Task> taskList;
        try {
            TaskQuery taskQuery = taskService.createTaskQuery().taskTenantId(tenantId).taskDueBefore(new Date());
            if (StringUtils.hasLength(variableName) && StringUtils.hasLength(variableValue)) {
                taskQuery.taskVariableValueEquals(variableName, variableValue);
            }

            taskList = taskQuery.listPage((current - 1) * pageSize, pageSize);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("查询失败：" + e.getMessage());
        }
        if (!CollectionUtils.isEmpty(taskList)) {
            List<TaskVO> resultList = new ArrayList<>();
            for (Task task : taskList) {
                TaskVO vo = new TaskVO();
                BeanUtils.copyProperties(task, vo);
                vo.setProperties(operateTaskService.findRunningTaskParams(task));
                Map<String, VariableInstance> variableInstances = taskService.getVariableInstances(task.getId());
                if (!CollectionUtils.isEmpty(variableInstances)) {
                    if (vo.getRunningVariables() == null) {
                        vo.setRunningVariables(new ArrayList<>(variableInstances.size()));
                    }
                    variableInstances.forEach((key, value) ->
                    {
                        vo.getRunningVariables().add((VariableInstanceEntityImpl) value);
                    });
                }
                vo.setTaskType(0);
                //任务锁状态
                vo.setLocked(checkTaskLock(task.getId()));
                resultList.add(vo);
            }
            Page<TaskVO> page = new Page<>(current, pageSize);
            page.setRecords(resultList);
            page.setTotal(taskService.createTaskQuery().taskCandidateOrAssigned(null).taskTenantId(tenantId).count());
            return ResponseResult.success(page);
        } else {
            return ResponseResult.error("所给参数查询不到任何任务！");
        }
    }

    @PostMapping(path = "/findDoneTaskByAssignee")
    @ApiOperation(value = "根据流程assignee查询当前人的已办办任务",
            notes = "根据流程assignee查询当前人的已办任务。返回值为包含taskID(任务ID),taskName(任务名称),taskCreateTime(任务的创建时间),taskAssignee(任务的办理人),processInstanceId(流程实例ID),executionId(执行对象ID),processDefinitionId(流程定义ID)字段的列表")
    public ResponseResult<Page<TaskVO>> findDoneTaskByAssignee(
            @ApiParam("代理人（用户）") @RequestParam(value = "assignee", required = false) String assignee,
            @ApiParam(value = "变量名") @RequestParam(value = "variableName", required = false) String variableName,
            @ApiParam(value = "变量值") @RequestParam(value = "variableValue", required = false) String variableValue,
            @ApiParam(value = "变量名Like") @RequestParam(value = "variableNameLike", required = false) String variableNameLike,
            @ApiParam(value = "变量值Like") @RequestParam(value = "variableValueLike", required = false) String variableValueLike,
            @ApiParam(value = "流程定义Key,多个用英文','隔开") @RequestParam(value = "processDefinedKey", required = false) String processDefinitionKey,
            @ApiParam(value = "流程实例id") @RequestParam(value = "processInstanceId", required = false) String processInstanceId,
            @ApiParam(value = "流程节点Key") @RequestParam(value = "taskKey", required = false) String taskKey,
            @ApiParam(value = "创建时间排序方向:1代表时间升序、-1代表时间降序") @RequestParam("sort") Integer sort,
            @ApiParam(value = "当前页码", example = "1") @RequestParam("current") Integer current,
            @ApiParam(value = "每页大小", example = "10") @RequestParam("pageSize") Integer pageSize,
            @ApiParam("租户id") @RequestParam("tenantId") String tenantId) {
        HistoricTaskInstanceQuery historicTaskInstanceQuery;
        if (sort == 1) {
            historicTaskInstanceQuery =
                    historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery().taskTenantId(tenantId).orderByHistoricTaskInstanceStartTime().asc();
        } else if (sort == -1) {
            historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery().taskTenantId(tenantId).orderByHistoricTaskInstanceStartTime().desc();
        } else {
            //默认按升序
            historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery().taskTenantId(tenantId);
        }
        if (StringUtils.hasLength(assignee)) {
            historicTaskInstanceQuery.taskAssignee(assignee);
            historicTaskInstanceQuery.taskInvolvedUser(assignee);
        }
        if (StringUtils.hasLength(variableName) && StringUtils.hasLength(variableValue)) {
            historicTaskInstanceQuery.taskVariableValueEquals(variableName, variableValue);
        }
        if (StringUtils.hasLength(processDefinitionKey)) {
            String[] split = processDefinitionKey.split(",");
            if (split.length > 1) {
                List<String> stringList = Arrays.asList(split);
                historicTaskInstanceQuery.processDefinitionKeyIn(stringList);
            } else {
                historicTaskInstanceQuery.processDefinitionKey(processDefinitionKey);
            }
        }
        if (StringUtils.hasLength(processInstanceId)) {
            historicTaskInstanceQuery.processInstanceId(processInstanceId);
        }
        if (StringUtils.hasLength(taskKey)) {
            historicTaskInstanceQuery.taskDefinitionKey(taskKey);
        }
        if (StringUtils.hasLength(variableNameLike) && StringUtils.hasLength(variableValueLike)) {
            historicTaskInstanceQuery.taskVariableValueLike(variableNameLike, variableValueLike);
        }
        List<HistoricTaskInstance> historicTaskInstances =
                historicTaskInstanceQuery.listPage((current - 1) * pageSize, pageSize);
        if (!CollectionUtils.isEmpty(historicTaskInstances)) {
            Page<TaskVO> page = new Page<>(current, pageSize);
            List<TaskVO> resultList = new ArrayList<>();
            for (HistoricTaskInstance task : historicTaskInstances) {
                TaskVO vo = new TaskVO();
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId())
                        .singleResult();
                vo.setProcinstCreateTime(historicProcessInstance.getStartTime());
                BeanUtils.copyProperties(task, vo);
                vo.setProperties(operateTaskService.findHistoryTaskParams(task));
                if (!StringUtils.isEmpty(task.getId())) {
                    HistoricTaskInstanceQuery historicTaskInstanceQuery1 =
                            historyService.createHistoricTaskInstanceQuery().taskId(task.getId());
                    if (historicTaskInstanceQuery1 != null) {
                        List<HistoricTaskInstance> historicTaskInstances1 = historicTaskInstanceQuery1.list();
                        if (!CollectionUtils.isEmpty(historicTaskInstances1)) {
                            for (HistoricTaskInstance historicTaskInstance : historicTaskInstances1) {
                                BeanUtils.copyProperties(historicTaskInstance, vo);
                                List<HistoricVariableInstance> historicVariableInstances =
                                        historyService.createHistoricVariableInstanceQuery()
                                                .taskId(historicTaskInstance.getId())
                                                .list();
                                if (!CollectionUtils.isEmpty(historicVariableInstances)) {
                                    List<HistoricVariableInstanceEntityImpl> historicTaskVariables = new ArrayList<>();
                                    for (HistoricVariableInstance historicVariableInstance : historicVariableInstances) {
                                        historicTaskVariables.add(
                                                (HistoricVariableInstanceEntityImpl) historicVariableInstance);
                                    }
                                    vo.setHistoryVariables(historicTaskVariables);
                                }
                                vo.setTaskType(1);
                            }
                        }
                    }
                }
                vo.setTaskType(1);
                resultList.add(vo);
            }
            page.setRecords(resultList);
            page.setTotal(historicTaskInstanceQuery.count());
            return ResponseResult.success(page);
        } else {
            return ResponseResult.error("未查询到已办任务");
        }
    }

    /**
     * 任务节点回退上步
     *
     * @param taskId 当前任务id
     */
    @GetMapping("/taskBack/{taskId}")
    @ApiOperation(value = "根据taskId回退跳转", notes = "taskId为当前任务id,任务节点回退上步")
    @Transactional
    public ResponseResult taskBack(@PathVariable("taskId") String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            return ResponseResult.error("参数taskId为必传参数!");
        }
        TaskVO vo = new TaskVO();
        try {
            //当前任务
            Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (currentTask == null) {
                return ResponseResult.error("不存在该任务！");
            }
            List<HistoricTaskInstance> historyList = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(currentTask.getProcessInstanceId())
                    .orderByHistoricTaskInstanceEndTime()
                    .desc()
                    .list();
            if (CollectionUtils.isEmpty(historyList)) {
                return ResponseResult.error("未查到回退目标节点!");
            }
            ResponseResult<List<UserTask>> nodePathResponse = processImageManager.getNodePath(currentTask.getProcessInstanceId(), taskId, currentTask.getTenantId());
            if (nodePathResponse.getCode() != 200) {
                return ResponseResult.error(nodePathResponse.getMsg());
            }
            List<UserTask> preNodeList = nodePathResponse.getData();
            if (CollectionUtils.isEmpty(preNodeList)) {
                return ResponseResult.error("未找到上一个任务");
            }
            UserTask targetNode = null;
            if (preNodeList.size() > 0) {
                List<HistoricTaskInstance> nodeTime = new ArrayList<>(preNodeList.size());
                preNodeList.forEach(node -> {
                    List<HistoricTaskInstance> nodeHis = historyList.stream().filter(item -> item.getTaskDefinitionKey().equals(node.getId()) && item.getEndTime() != null).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(nodeHis))
                        nodeTime.add(nodeHis.get(0));
                });
                List<HistoricTaskInstance> sortedNode =
                        nodeTime.stream().sorted(Comparator.comparing(HistoricTaskInstance::getEndTime).reversed()).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(sortedNode)) {
                    for (UserTask node : preNodeList) {
                        if (node.getId().equals(sortedNode.get(0).getTaskDefinitionKey())) {
                            targetNode = node;
                            break;
                        }
                    }
                }
            } else {
                targetNode = preNodeList.get(0);
            }
            if (targetNode == null) {
                return ResponseResult.error("未找到上一个任务");
            }
            Map<String, HistoricTaskInstance> historicMap = historyList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, a -> a, (k1, k2) -> k1));
            String assignee = historicMap.get(targetNode.getId()).getAssignee();
            if (StringUtils.isEmpty(assignee)) {
                return ResponseResult.error("回退目标节点没有执行人!");
            }

            processEngine.getManagementService().executeCommand(new JumpAnyWhereCmd(taskId, targetNode.getId()));
            //给跳转目标任务赋值assignee
            Task targetTask = taskService.createTaskQuery()
                    .processInstanceId(currentTask.getProcessInstanceId())
                    .active()
                    .singleResult();
            taskService.setAssignee(targetTask.getId(), assignee);
            BeanUtils.copyProperties(targetTask, vo);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("任务回退跳转失败!");
        }

        return ResponseResult.success(vo);
    }


    /**
     * 任务节点回退上步
     *
     * @param taskId 当前任务id
     */
    @GetMapping("/taskBack1/{taskId}")
    @ApiOperation(value = "根据taskId回退跳转", notes = "taskId为当前任务id,任务节点回退上步")
    @Transactional
    public ResponseResult taskBack1(@PathVariable("taskId") String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            return ResponseResult.error("参数taskId为必传参数!");
        }
        TaskVO vo = new TaskVO();
        try {
            //当前任务
            Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (currentTask == null) {
                return ResponseResult.error("不存在该任务！");
            }
            // 取得所有历史任务按时间降序排序
            List<HistoricTaskInstance> hisList = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(currentTask.getProcessInstanceId())
                    .orderByTaskCreateTime()
                    .desc()
                    .list();
            // 历史任务中没有说明任务刚刚启动，不需要回退
            if (CollectionUtils.isEmpty(hisList)) {
                return ResponseResult.error("没有前置任务可回退!");
            }
            LinkedHashMap<String, Integer> nodeCount = new LinkedHashMap<>();
            for (HistoricTaskInstance item : hisList) {
                if (item.getEndTime() == null)
                    continue; //未完成不计入
                if (item.getTaskDefinitionKey().equals(currentTask.getTaskDefinitionKey()))
                    continue; //多实例产生的任务不计入
                Integer count = nodeCount.get(item.getTaskDefinitionKey());
                if (count == null)
                    count = 1;
                else
                    count = count + 1;
                nodeCount.put(item.getTaskDefinitionKey(), count);
            }
            // 从流程图中查找map中的任务，判断是否为当前任务的上一个任务
            BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());
            LinkedHashMap<String, UserTask> userTaskMap = new LinkedHashMap<>();
            // 过滤非用户任务 可能需要
            nodeCount.forEach((key, value) -> {
                FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(key);
                if (flowElement instanceof UserTask) {
                    userTaskMap.put(key, (UserTask) flowElement);
                }
            });
            MultiInstanceLoopCharacteristics loopCharacteristics = userTaskMap.get("").getLoopCharacteristics();
//            ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
//            ManagementService managementService = defaultProcessEngine.getManagementService();
//            // 跳转
//            并行任务
//            多实例任务
//            单任务
//            managementService.executeCommand(new JumpCmd(currentTask.getId(), first.getKey()));
            // 恢复执行人
        } catch (Exception e) {
            return ResponseResult.error("任务节点回退跳转失败!");
        }
        return ResponseResult.success(vo);
    }

    /**
     * 获取已执行的任务列表
     *
     * @param tenantId
     * @param processInstanceId
     * @return
     */
    @GetMapping("/history/tasks/{tenantId}")
    @ApiOperation("根据实例id及tenantId,获取已执行的历史任务")
    public ResponseResult<List<HistoricTaskInstance>> getHistoryTasks(@PathVariable("tenantId") String tenantId, @RequestParam String processInstanceId) {
        // 取得所有历史任务按时间升序排序
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .taskTenantId(tenantId)
                .orderByTaskCreateTime()
                .asc()
                .list();
        List<HistoricTaskInstance> resultCollects =
                htiList.stream().filter(s -> s.getEndTime() != null).collect(Collectors.toList());
        return ResponseResult.success(resultCollects);
    }

    /**
     * 任意回退到已执行的节点(修改数据库版本)
     *
     * @return
     */
    @PostMapping("/sql/random/back")
    @ApiOperation("任意回退到已执行的节点")
    public ResponseResult<Integer> jumpOrReturn(@RequestParam String currentTaskId, @RequestParam String backToTaskId) {
        /*
         *
         * 任务回退
         *
         * 需求：从当前任务 任意回退至已审批任务
         * 方法：通过activiti源代码里的sqlSession直接修改数据库
         *
         * 第一步 完成历史TASK覆盖当前TASK
         * 用hi_taskinst修改当前ru_task
         * ru_task.ID_=hi_taskinst.ID_
         * ru_task.NAME_=hi_taskinst.NAME_
         * ru_task.TASK_DEF_KEY_=hi_taskinst.TASK_DEF_KEY_
         *
         * 第二步
         * 修改当前任务参与人列表
         * ru_identitylink 用ru_task.ID_去ru_identitylink 索引
         * ru_identitylink.TASK_ID_=hi_taskinst.ID_
         * ru_identitylink.USER_ID=hi_taskinst.ASSIGNEE_
         *
         * 第三步修改流程记录节点 把ru_execution的ACT_ID_ 改为hi_taskinst.TASK_DEF_KEY_
         *
         */
        int result = FlowProvider.I_NO_OPERATION;
        SqlSession sqlSession = getSqlSession();
        TaskEntity currentTaskEntity = getCurrentTaskEntity(currentTaskId);
        HistoricTaskInstanceEntity backToHistoricTaskInstanceEntity = getHistoryTaskEntity(backToTaskId);
        if (currentTaskEntity == null || backToHistoricTaskInstanceEntity == null) {
            return ResponseResult.success(I_TASK_NOT_FOUND);
        }
        String processDefinitionId = currentTaskEntity.getProcessDefinitionId();
        String executionId = currentTaskEntity.getExecutionId();
        String currentTaskEntityId = currentTaskEntity.getId();
        String backToHistoricTaskInstanceEntityId = backToHistoricTaskInstanceEntity.getId();
        String backToTaskDefinitionKey = backToHistoricTaskInstanceEntity.getTaskDefinitionKey();
        String backToAssignee = backToHistoricTaskInstanceEntity.getAssignee();
        boolean success = false;
        try {
            // 1.
            StepOne_use_hi_taskinst_to_change_ru_task(sqlSession, currentTaskEntity, backToHistoricTaskInstanceEntity);
            // 2.
            StepTwo_change_ru_identitylink(sqlSession, currentTaskEntityId, backToHistoricTaskInstanceEntityId,
                    backToAssignee);
            // 3.
            StepThree_change_ru_execution(sqlSession, executionId, processDefinitionId, backToTaskDefinitionKey);
            success = true;
        } catch (Exception e) {
            throw new ActivitiException("dbBackTo Exception", e);
        } finally {
            if (success) {
                sqlSession.commit();
                result = I_DONE;
            } else {
                sqlSession.rollback();
                result = I_ROLLBACK;
            }
            sqlSession.close();
        }
        return ResponseResult.success(result);
    }

    /**
     * 任意回退到已执行的节点(跳转方式)
     *
     * @return
     */
    @PostMapping("/random/back")
    @ApiOperation("任意回退到已执行的节点")
    public ResponseResult<Void> turnTransition(@RequestParam String processInstanceId, @RequestParam String currentTaskId, @RequestParam String targetNodeId) {
        try {
            List<HistoricTaskInstance> historyList = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .taskDefinitionKey(targetNodeId)
                    .orderByHistoricTaskInstanceEndTime()
                    .desc()
                    .list();
            if (CollectionUtils.isEmpty(historyList)) {
                return ResponseResult.error("未查到回退目标节点!");
            }
            String assignee = historyList.get(0).getAssignee();
            if (StringUtils.isEmpty(assignee)) {
                return ResponseResult.error("回退目标节点没有执行人!");
            }
            processEngine.getManagementService().executeCommand(new JumpAnyWhereCmd(currentTaskId, targetNodeId));
            //给跳转目标任务赋值assignee
            Task targetTask = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .taskDefinitionKey(targetNodeId)
                    .active()
                    .singleResult();
            taskService.setAssignee(targetTask.getId(), assignee);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error("任务回退跳转失败!");
        }
        return ResponseResult.success();
    }

    @GetMapping("/getProcessInstances/{tenantId}")
    @ApiOperation("根据系统id,查询未删除的流程实例情况")
    public ResponseResult getProcessInstances(@PathVariable("tenantId") String tenantId,
                                              @ApiParam(value = "创建时间排序方向:1代表时间升序、-1代表时间降序") @RequestParam("sort") Integer sort) {
        //存放流程实例的集合
        List list = new ArrayList<>();
        HistoricProcessInstanceQuery historicProcessInstanceQuery;
        try {
            //创建已生成的流程实例查询对象
            if (sort == 1) {
                historicProcessInstanceQuery =
                        historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().asc();
            } else if (sort == -1) {
                historicProcessInstanceQuery =
                        historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().desc();
            } else {
                //默认按升序
                historicProcessInstanceQuery =
                        historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime();
            }
            List<HistoricProcessInstance> historicProcessInstanceList =
                    historicProcessInstanceQuery.processInstanceTenantId(tenantId).notDeleted().list();
            for (HistoricProcessInstance historicProcessInstance : historicProcessInstanceList) {
                ProcessInstanceVO processInstanceVO = new ProcessInstanceVO();
                BeanUtils.copyProperties(historicProcessInstance, processInstanceVO);
                if (processInstanceVO.getEndTime() != null) {
                    processInstanceVO.setStatus("已完成");
                } else {
                    processInstanceVO.setStatus("未完成");
                }
                list.add(processInstanceVO);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return ResponseResult.error("查询流程实例失败!");
        }
        return ResponseResult.success(list);
    }

    @GetMapping("/getImageByProcessInstanceId/{processInstanceId}")
    @ApiOperation("根据流程实例id查看实时流程图")
    public void getImageByProcessInstanceId(HttpServletResponse response,
                                            @ApiParam(value = "流程实例id", required = true) @PathVariable("processInstanceId") String processInstanceId,
                                            @ApiParam("租户id") @RequestParam("tenantId") String tenantId) {
        try {
            InputStream is = processImageManager.getFlowImgByProcInstId(processInstanceId, tenantId);
            if (is == null) {
                return;
            }
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = is.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
            is.close();
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return;
        }
        return;
    }

    @GetMapping("/getNodePath/{processInstanceId}")
    @ApiOperation("根据流程实例和任务id获取当前任务的执行顺序")
    public ResponseResult getNodePath(@PathVariable("processInstanceId") String processInstanceId,
                                      @ApiParam("任务id") @RequestParam("taskId") String taskId,
                                      @ApiParam("租户id") @RequestParam("tenantId") String tenantId) {
        return processImageManager.getNodePath(processInstanceId, taskId, tenantId);
    }

    @GetMapping("/getTasksByProcessInstanceId/{tenantId}/{processInstanceId}")
    @ApiOperation("根据流程实例id查看已办任务和待办任务以及任务变量")
    public ResponseResult getTasksByProcessInstanceId(
            @ApiParam(value = "系统id", required = true) @PathVariable("tenantId") String tenantId,
            @ApiParam(value = "流程实例id", required = true) @PathVariable("processInstanceId") String processInstanceId,
            @ApiParam(value = "创建时间排序方向:1代表时间升序、-1代表时间降序") @RequestParam("sort") Integer sort) {
        List<TaskVO> listTotal = new ArrayList<>();
        HistoricTaskInstanceQuery historicTaskInstanceQuery;
        if (sort == 1) {
            historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                    .taskTenantId(tenantId)
                    .processInstanceId(processInstanceId).orderByTaskCreateTime().asc();
        } else if (sort == -1) {
            historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                    .taskTenantId(tenantId)
                    .processInstanceId(processInstanceId).orderByTaskCreateTime().desc();
        } else {
            //默认按升序
            historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                    .taskTenantId(tenantId)
                    .processInstanceId(processInstanceId);
        }
        List<HistoricTaskInstance> historicTaskInstances = historicTaskInstanceQuery.list();
        if (!CollectionUtils.isEmpty(historicTaskInstances)) {
            for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
                TaskVO vo = new TaskVO();
                BeanUtils.copyProperties(historicTaskInstance, vo);
                List<HistoricVariableInstance> historicVariableInstances =
                        historyService.createHistoricVariableInstanceQuery()
                                .taskId(historicTaskInstance.getId())
                                .list();
                if (!CollectionUtils.isEmpty(historicVariableInstances)) {
                    List<HistoricVariableInstanceEntityImpl> historicTaskVariables = new ArrayList<>();
                    for (HistoricVariableInstance historicVariableInstance : historicVariableInstances) {
                        historicTaskVariables.add(
                                (HistoricVariableInstanceEntityImpl) historicVariableInstance);
                    }
                    vo.setHistoryVariables(historicTaskVariables);
                }
                if (historicTaskInstance.getEndTime() != null) {
                    vo.setTaskType(1);
                } else {
                    vo.setTaskType(0);
                }
                listTotal.add(vo);
            }
        }
        return ResponseResult.success(listTotal);
    }


    @DeleteMapping("/deleteProcessInstance/{processInstanceId}")
    @ApiOperation("删除流程实例")
    public ResponseResult deleteProcessInstance(@PathVariable(value = "processInstanceId") String processInstanceId,
                                                @ApiParam(value = "删除原因", required = true) @RequestParam("reason") String reason) {
        try {
            log.info("=============删除流程实例============");
            List<ProcessInstance> processInstances =
                    runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).list();
            if (processInstances.isEmpty()) {
                // 历史流程实例
                List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery()
                        .processInstanceId(processInstanceId).list();
                if (historicProcessInstances.isEmpty()) {
                    String msg = "No process instances with the ID: " + processInstanceId;
                    log.error(msg);
                    throw new ActivitiException(msg);
                }
                historyService.deleteHistoricProcessInstance(processInstanceId);
                return ResponseResult.success("删除流程实例成功！");
            }
            runtimeService.deleteProcessInstance(processInstanceId, reason);
            return ResponseResult.success("删除流程实例成功！");
        } catch (ActivitiException e) {
            return ResponseResult.error("删除流程实例失败！");
        }
    }

    @GetMapping(path = "/testversion")
    public ResponseResult testversion() {

        Runtime rt = Runtime.getRuntime();
        double free = rt.freeMemory() / 1024 / 1024;
        double total = rt.totalMemory() / 1024 / 1024;


        Map map = new HashMap();
        map.put("version", "0.5--");

        String hostname = System.getenv("HOSTNAME");
        map.put("hostname", hostname);

        map.put("freemem", "" + free);
        map.put("totalmem", "" + total);

        map.put("thread", "" + Thread.activeCount());

        System.out.println("map:" + map);

        return ResponseResult.success("map:" + map);
    }

    /**
     * 检查任务锁状态
     *
     * @param taskId
     */
    public Boolean checkTaskLock(String taskId) {
        //先校验该任务是否为预处理的任务
        Object cacheObject = cache.get("timing_flow_task_lock_" + taskId);
        String value = null;
        if (cacheObject != null)
            value = (String) cacheObject;
        if (StringUtils.isEmpty(value)) {
            return false;
        } else {
            return true;
        }
    }

    private static void StepThree_change_ru_execution(SqlSession sqlSession, String executionId,
                                                      String processDefinitionId, String backToTaskDefinitionKey) throws Exception {
        List<ExecutionEntity> currentExecutionEntityList = sqlSession.selectList("selectExecution", executionId);
        if (currentExecutionEntityList.size() > 0) {
            FlowElement flowElement = getFlowElement(processDefinitionId, backToTaskDefinitionKey);
            Iterator<ExecutionEntity> execution = currentExecutionEntityList.iterator();
            while (execution.hasNext()) {
                ExecutionEntity e = execution.next();
                e.setCurrentFlowElement(flowElement);
                p(sqlSession.update("updateExecution", e));
            }
        }
    }

    private static void StepTwo_change_ru_identitylink(SqlSession sqlSession, String currentTaskEntityId,
                                                       String backToHistoricTaskInstanceEntityId, String backToAssignee) throws Exception {
        ListQueryParameterObject para = new ListQueryParameterObject();
        para.setParameter(currentTaskEntityId);
        List<IdentityLinkEntity> currentTaskIdentityLinkEntityList = sqlSession.selectList("selectIdentityLinksByTask",
                para);
        if (currentTaskIdentityLinkEntityList.size() > 0) {
            Iterator<IdentityLinkEntity> identityLinkEntityList = currentTaskIdentityLinkEntityList.iterator();
            IdentityLinkEntity identityLinkEntity;
            TaskEntity tmpTaskEntity;
            tmpTaskEntity = new TaskEntityImpl();
            tmpTaskEntity.setId(backToHistoricTaskInstanceEntityId);
            while (identityLinkEntityList.hasNext()) {
                identityLinkEntity = identityLinkEntityList.next();
                identityLinkEntity.setTask(tmpTaskEntity);
                identityLinkEntity.setUserId(backToAssignee);
                Map<String, Object> parameters = new HashMap<String, Object>();
                parameters.put("id", identityLinkEntity.getId());
                sqlSession.delete("deleteIdentityLink", parameters);
                sqlSession.insert("insertIdentityLink", identityLinkEntity);
            }
        }
    }

    private static void StepOne_use_hi_taskinst_to_change_ru_task(SqlSession sqlSession, TaskEntity currentTaskEntity,
                                                                  HistoricTaskInstanceEntity backToHistoricTaskInstanceEntity) throws Exception {
        sqlSession.delete("deleteTask", currentTaskEntity);
        currentTaskEntity.setName(backToHistoricTaskInstanceEntity.getName());
        currentTaskEntity.setTaskDefinitionKey(backToHistoricTaskInstanceEntity.getTaskDefinitionKey());
        currentTaskEntity.setId(backToHistoricTaskInstanceEntity.getId());
        sqlSession.insert("insertTask", currentTaskEntity);
    }

    public static void p(Object o) {
        System.out.println(o);
    }

    private static FlowElement getFlowElement(String processDefinitionId, String taskDefinitionKey) {
        boolean b;
        List<FlowElement> flowElements = (List<FlowElement>) ProcessDefinitionUtil.getProcess(processDefinitionId).getFlowElements();
        for (FlowElement flowElement : flowElements) {
            b = flowElement.getId().equals(taskDefinitionKey);
            if (b) {
                return flowElement;
            }
        }
        return null;
    }

    private static TaskEntity getCurrentTaskEntity(String id) {
        return (TaskEntity) ProcessEngines.getDefaultProcessEngine().getTaskService().createTaskQuery().taskId(id).singleResult();
    }

    private static HistoricTaskInstanceEntity getHistoryTaskEntity(String id) {
        return (HistoricTaskInstanceEntity) ProcessEngines.getDefaultProcessEngine().getHistoryService().createHistoricTaskInstanceQuery()
                .taskId(id).singleResult();
    }

    private static SqlSession getSqlSession() {
        ProcessEngineImpl processEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
        DbSqlSessionFactory dbSqlSessionFactory = (DbSqlSessionFactory) processEngine.getProcessEngineConfiguration()
                .getSessionFactories().get(DbSqlSession.class);
        SqlSessionFactory sqlSessionFactory = dbSqlSessionFactory.getSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }
}
